<template>
    <el-upload
        ref="upload"
        list-type="picture-card"
        :accept="props.accept"
        :show-file-list="false"
        :limit="1"
        class="prize-image-upload"
        :class="{ uploaded: Boolean(props.modelValue) }"
        :on-exceed="handleExceed"
        :before-upload="handBeforeUpload"
        :http-request="onHttpRequest">
        <div v-if="props.modelValue" class="reupload">
            <div v-if="!props.disabled" class="el-upload-list__item-menu">
                <template v-if="props.defaultImage">
                    <span> 更换 </span>
                    <span @click.stop="handleResetFile"> 默认 </span>
                </template>
                <template v-else>
                    <span> {{ props.label }} </span>
                </template>
            </div>
            <img class="el-upload-list__item-thumbnail" :src="props.modelValue" alt="" />
        </div>
        <div v-else class="upload-box">
            <el-icon><Plus /></el-icon>
            <span class="upload-tip">添加图片</span>
        </div>
        <template #tip>
            <span class="upload-tip">
                <slot name="tip"></slot>
            </span>
        </template>
    </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { ElMessage, genFileId } from 'element-plus';
import type { UploadInstance, UploadProps, UploadRawFile, UploadRequestOptions } from 'element-plus';
import Decimal from 'decimal.js';

import { uploadFile2 } from '@/api/common';

const props = defineProps({
    modelValue: {
        require: true,
        type: String,
        default: ''
    },
    label: {
        type: String,
        default: '重新上传'
    },
    // 默认图片
    defaultImage: {
        type: String,
        default: ''
    },
    // 上传格式限制
    accept: {
        type: String,
        default: '.jpg,.png,.gif,.jpeg'
    },
    // 上传大小，单位kb, 默认2m
    size: {
        type: [String, Number],
        default: 2048
    },
    // 禁用状态下
    disabled: {
        type: Boolean,
        default: false
    }
});
const emit = defineEmits(['update:modelValue', 'uploadAfter']);

/* ----------------------------奖品图片-start---------------------------- */
const upload = ref<UploadInstance>();
// 超出时删除上一个
const handleExceed: UploadProps['onExceed'] = files => {
    upload.value?.clearFiles();
    const file = files[0] as UploadRawFile;
    file.uid = genFileId();
    upload.value?.handleStart(file);
    upload.value?.submit();
};
/**
 * @desc 上传校验;
 */
const handBeforeUpload = (rawFile: UploadRawFile) => {
    const type = props.accept.split(',').map(item => item.substring(1));
    const filetype = rawFile.name.split('.').pop() ?? '';
    if (!type.includes(filetype)) {
        ElMessage.warning(`请上传${type.join('、')}文件!`);
        return false;
    }

    const kbSize = Number(props.size) || 0;
    const mbSize = Number(Decimal.div(kbSize, 1024));
    const maxSize = Number(Decimal.mul(1024, kbSize));
    if (rawFile.size > maxSize) {
        ElMessage.warning(`文件大小不能超过${Math.floor(mbSize) === mbSize ? mbSize + 'M' : kbSize + 'kb'}!`);
        return false;
    }
    return true;
};
/**
 * @desc 自定义上传文件;
 */
const onHttpRequest = async (options: UploadRequestOptions) => {
    try {
        // 上传
        const res = await uploadFile2({
            file: options.file,
            fileName: options.file.name
        });
        // 校验
        emit('update:modelValue', res.url);
        emit('uploadAfter', res.url);
    } catch {
        emit('update:modelValue', '');
    }
};

const handleResetFile = () => {
    emit('update:modelValue', props.defaultImage);
};
/* ----------------------------奖品图片-end---------------------------- */
</script>
<style lang="scss" scoped>
.prize-image-upload {
    :deep(.el-upload),
    :deep(.el-upload-list__item) {
        width: 100px;
        height: 100px;
        background-color: #fff;
        border-radius: 4px;
    }

    :deep(.el-upload) {
        border: 1px dashed #eaeaea;
        vertical-align: bottom;
        margin-right: 8px;

        &:hover {
            border-color: var(--el-color-primary);
        }
    }

    &.uploaded {
        :deep(.el-upload) {
            border: 1px solid #eaeaea;
        }
    }
}

.hide-uploader {
    :deep(.el-upload) {
        display: none;
    }
}

.reupload {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 4px;
    overflow: hidden;

    .el-upload-list__item-thumbnail {
        width: 100%;
        height: 100%;
    }

    .el-upload-list__item-menu {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 28.8px;
        line-height: 28.8px;
        background-color: rgb(0 0 0 / 50%);
        text-align: center;

        > span {
            color: #fff;
            font-size: 14px;

            &:nth-child(2) {
                margin-left: 12px;
            }
        }
    }
}

.el-upload-list__item-actions {
    align-items: flex-end;
}

.upload-tip {
    display: inline-block;
    font-size: 14px;
    font-family: PingFangSC-Regular, 'PingFang SC';
    font-weight: 400;
    color: #999;
    line-height: normal;
    vertical-align: bottom;
}

.upload-box {
    display: flex;
    flex-direction: column;
    align-items: center;
}
</style>
